package cn.chaos.bio.exercise;

import org.springframework.util.StringUtils;

import java.io.*;
import java.net.Socket;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RequestProcessor implements Runnable {

    private final static Logger logger = Logger.getLogger(RequestProcessor.class.getCanonicalName());

    private File rootDirectory;
    private String indexFileName = "index.html";
    private Socket connection;


    public RequestProcessor(File rootDirectory, String indexFileName, Socket connection) {
        if (rootDirectory.isFile()) {
            throw new IllegalArgumentException(
                    "rootDirectory must be a directory, not a file"
            );
        }
        try {
            rootDirectory = rootDirectory.getCanonicalFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.rootDirectory = rootDirectory;
        if (StringUtils.hasText(indexFileName)) {
            this.indexFileName = indexFileName;
        }
        this.connection = connection;
    }



    @Override
    public void run() {

        String root = rootDirectory.getPath();
        try {
            BufferedOutputStream raw = new BufferedOutputStream(connection.getOutputStream());
            Writer out = new OutputStreamWriter(raw);
            Reader in = new InputStreamReader(
                    new BufferedInputStream(
                            connection.getInputStream()
                    ), StandardCharsets.UTF_8
            );
            BufferedReader br = new BufferedReader(in);

//            StringBuilder requestLine = new StringBuilder();
//            while (true) {
//                int c = in.read();
//                if (c == '\r' || c == '\n') break;
//                requestLine.append((char) c);
//            }
//            String get = requestLine.toString();

            List<String> requestLines = new ArrayList<>();

            while (true) {
                String line = br.readLine();
                if (StringUtils.isEmpty(line)) {
                    break;
                }
                requestLines.add(line);
                System.out.println(">> "+ line);
            }
            System.out.println(">> ");
            String get = requestLines.get(0);
            logger.info(connection.getRemoteSocketAddress() + " " + get);

            String[] tokens = get.split("\\s+");
            String method = tokens[0];
            String version = "";
            if ("GET".equals(method)) {
                String fileName = tokens[1];
                if (fileName.endsWith("/")) {
                    fileName += indexFileName;
                }

                String contentType = URLConnection.getFileNameMap().getContentTypeFor(fileName);
                if (tokens.length > 2) {
                    version = tokens[2];
                }
                File theFile = new File(rootDirectory, fileName.substring(1, fileName.length()));

                if (theFile.canRead()
                    && theFile.getCanonicalPath().startsWith(root)) {
                    byte[] theData = Files.readAllBytes(theFile.toPath());
                    if (version.startsWith("HTTP/")) {
                        sendHeader(out, "HTTP/1.0 200 OK", contentType, theData.length);
                    }


                    raw.write(theData);
                    raw.flush();
                } else {
                    String body = new StringBuilder("<html>\r\n")
                            .append("<head><title>File Not Found</title>\r\n")
                            .append("</head>\r\n")
                            .append("<body>")
                            .append("<h1>HTTP Error 404: File Not Found</h1>\r\n")
                            .append("</body></html>\r\n").toString();
                    if (version.startsWith("HTTP/")) {
                        sendHeader(out, "HTTP/1.0 404 File Not Found",
                                "text/html charset=utf-8", body.length());
                    }
                    out.write(body);
                    out.flush();
                }
            } else {
                // 不是 GET
            }
        } catch (IOException e) {
            logger.log(Level.WARNING,
                    "Error talking to "+ connection.getRemoteSocketAddress(), e);
        } finally {
            try {
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void sendHeader(Writer out, String responseCode, String contentType, int length) throws IOException {

        out.write(responseCode + "\r\n");
        Date now = new Date();
        out.write("Date: "+ now + "\r\n");
        out.write("Server: JHttpServerBio 1.0\r\n");
        out.write("Content-Type: "+ contentType + "\r\n");
        out.write("Content-Length: "+ length + "\r\n");
        out.write("\r\n");
        out.flush();
    }
}
